package com.lyb269.thread;

import org.junit.Test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 线程同步 ReentrantLock与synchronized
 * 1.两种形式实现线程安全
 * 2.二者性能对比
 */
public class SyncTest {

    //非同步的测试
    @Test
    public void asyncTest(){
        Thread t = new Thread(() -> {
            for (int i = 0; i < 5; i++){
                System.out.println(Thread.currentThread().getName()+"-->"+i);
            }
        });

        Thread thread1 = new Thread(t);
        thread1.start();
        Thread thread2 = new Thread(t);
        thread2.start();
        while (thread1.isAlive() && thread2.isAlive()){
            //等待两个线程执行完
        }
        //Thread-1-->0  //Thread-2-->0
        //Thread-2-->1  //Thread-2-->2
        //Thread-2-->3  //Thread-2-->4
        //Thread-1-->1  //Thread-1-->2
        //Thread-1-->3  //Thread-1-->4
        //两个线程交叉执行,互相抢占资源,不是线程安全的
    }

    //同步的测试  synchronized
    @Test
    public void synchronizedTest(){
        Thread t = new Thread(() -> {
            synchronized (this){
                for (int i = 0; i < 2; i++){
                    System.out.println(Thread.currentThread().getName()+"-->"+i);
                }
            }
        });

        ExecutorService service = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++){
            service.execute(t);
        }
        //pool-1-thread-1-->0    pool-1-thread-1-->1
        //pool-1-thread-2-->0    pool-1-thread-2-->1
        //pool-1-thread-3-->0    pool-1-thread-3-->1
        //pool-1-thread-4-->0    pool-1-thread-4-->1
        //pool-1-thread-1-->0    pool-1-thread-1-->1  这里跟第一个线程名称一样,这是因为newCachedThreadPool()是可回收的线程池,这里也间接验证了这个
        //pool-1-thread-5-->0    pool-1-thread-5-->1
        //pool-1-thread-6-->0    pool-1-thread-6-->1
        //pool-1-thread-7-->0    pool-1-thread-7-->1
        //pool-1-thread-8-->0    pool-1-thread-8-->1
        //pool-1-thread-9-->0    pool-1-thread-9-->1
        //每个线程循环两次,线程安全,不存在抢占资源的情况
    }

    //同步的测试  ReentrantLock
    @Test
    public void reentrantLockTest(){
        ReentrantLock lock = new ReentrantLock();
        Thread t = new Thread(() -> {
            //上锁
            lock.lock();
            try{
                for (int i = 0; i < 2; i++){
                    System.out.println(Thread.currentThread().getName()+"-->"+i);
                }
            }finally {
                //释放锁
                lock.unlock();
            }

        });

        ExecutorService service = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++){
            service.execute(t);
        }
        //打印效果同synchronizedTest(),说明同样是线程安全的
    }

    //同步的测试  ReentrantLock与synchronized性能测试
    @Test
    public void performanceTest(){
        ReentrantLock lock = new ReentrantLock();
        Thread t = new Thread(() -> {
            //上锁
            lock.lock();
            try{
                for (int i = 0; i < 50000; i++){
                    //循环一定的次数
                }
            }finally {
                //释放锁
                lock.unlock();
            }
        });
        Thread t2 = new Thread(() -> {
            synchronized (this){
                for (int i = 0; i < 50000; i++) {
                    //循环一定的次数
                }
            }
        });

        long start = System.currentTimeMillis();
        ExecutorService service = Executors.newCachedThreadPool();
        for (int i = 0; i < 10000000; i++){
            service.execute(t);
        }
        long end = System.currentTimeMillis();
        System.out.println("ReentrantLock方式执行时间:"+(end-start));

        start = System.currentTimeMillis();
        service = Executors.newCachedThreadPool();
        for (int i = 0; i < 10000000; i++){
            service.execute(t2);
        }
        end = System.currentTimeMillis();
        System.out.println("synchronized方式执行时间:"+(end-start));

        //第一次执行
        //ReentrantLock方式执行时间:19179
        //synchronized方式执行时间:18913

        //第二次执行
        //ReentrantLock方式执行时间:20578
        //synchronized方式执行时间:23596

        //第三次执行
        //ReentrantLock方式执行时间:24055
        //synchronized方式执行时间:23750

        //第四次执行
        //ReentrantLock方式执行时间:20452
        //synchronized方式执行时间:23634

        //4次测试,发现,性能上没多大的差异,都是20秒上下(这个值电脑配置的不同可能存在差异)
    }


}

